AD LDAP (389)
Lightweight Directory Access Protocol
We can query an LDAP server from a Linux machine with ldapsearch
sudo pacman -S openldap
ldapsearch -x -H ldap://IP -D "CN=oscar,CN=Users,DC=sequel,DC=htb"
-w "Password123!" -b "DC=sequel,DC=htb" "objectClass=user"
ldapwhoami -H ldap://IP -D "CN=oscar,CN=Users,DC=sequel,DC=htb"
-w "Password123!"
Search All Users
$Filter = "(objectClass=user)"
$RootOU = "DC=hexdump,DC=lab"
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($RootOU$")
$Searcher.Filter = $Filter
$Searcher.SearchScope = "Subtree"
$Searcher.FindAll()
LdapDomainDump
Check for unauthenticated binds
ldapdomaindump ldap://<DC_IP>
LDAPSearch
ldapsearch -x -H ldap://192.168.214.122
Limit the search scope to the base DN (distinguished name), which means it will only retrieve information from the root of the directory tree. namingContexts attribute, tells you the root naming contexts (base DNs) that the LDAP server holds.
ldapsearch -x -H ldap://192.168.214.122 -s base namingcontexts
List all LDAP entries with base DN 'domain com'
ldapsearch -x -H ldap://192.168.214.122 -b "DC=domain,DC=com"
Authenticated LDAPSearch
Basic syntax template, -x is simple auth, -H for the LDAP URI, -D is the bind distinguished name, -w for the password, -b is the base distinguished name, the LDAP search filter with filter and attributes for the optional attributes to retrieve.
ldapsearch -x -H ldap://<DC_IP_or_Hostname> -D '<bind_DN>' -w '<password>' -b '<base_DN>' '<filter>' <attributes>
Determine base DN
ldapsearch -x -H ldap://<DC_IP> -s base namingcontexts
Dump all domain info (no filter)
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec'
Enumerate users
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(objectClass=user)' sAMAccountName cn mail memberOf userAccountControl
Enumerate groups
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(objectClass=group)' cn member
Enumerate domain admins
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(&(objectClass=user)(memberOf=CN=Domain Admins,CN=Users,DC=access,DC=offsec))' sAMAccountName cn
Enumerate OUs
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(objectClass=organizationalUnit)' ou
Look for computers
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(objectClass=computer)' cn operatingSystem dNSHostName
Look for password policies
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(objectClass=domain)' maxPwdAge minPwdLength lockoutThreshold lockoutDuration
List group memberships of a specific user
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(sAMAccountName=target_user)' memberOf
Search for description fields (can contain passwords or notes)
ldapsearch -x -H ldap://<DC_IP> -D 'user@access.offsec' -w '<password>' -b 'dc=access,dc=offsec' '(sAMAccountName=target_user)' memberOf
Unauthenticated LDAPSearch
First check if anonymous bind works
ldapsearch -x -H ldap://<DC_IP> -s base
Try anonymous enumeration (no creds)
ldapsearch -x -H ldap://<DC_IP> -s base namingcontexts
List users
ldapsearch -x -H ldap://<DC_IP> -b "dc=access,dc=offsec" "(objectClass=user)" sAMAccountName cn
List groups
ldapsearch -x -H ldap://<DC_IP> -b "dc=access,dc=offsec" "(objectClass=group)" cn
List computers
ldapsearch -x -H ldap://<DC_IP> -b "dc=access,dc=offsec" "(objectClass=computer)" cn dNSHostName
Search for interesting fields
ldapsearch -x -H ldap://<DC_IP> -b "dc=access,dc=offsec" "(description=*)" sAMAccountName description